#include "SignUpService.h"
#include "CryptoUtil.h"
#include "SignUp.pb.h"

#include <signal.h>

#include <workflow/WFFacilities.h>
#include <workflow/MySQLResult.h>
#include <workflow/WFTaskFactory.h>
#include <string>


using namespace srpc;
using namespace protocol;
using std::string;

namespace {

	WFFacilities::WaitGroup wait_group(1);

	//默认的注册服务器的端口
	constexpr const unsigned short DEFAULT_SIGNUP_PORT = 1234;
	//默认的注册服务器的ip
	constexpr const char* DEFAULT_SIGNUP_IP = "127.0.0.1";
	//mysql的url
	constexpr const char* MYSQL_URL = "mysql://root:123@127.0.0.1/CloudDisk2";
	//最大重试次数
	constexpr const int RE_TRY_MAX = 3;

	void sig_handler(int signo)
	{
		wait_group.done();
	}

	/* ************************************************************************************ */
	/* *******************************注册************************************************* */
	/* ************************************************************************************ */

	void handleSignUp(::l::SignUpResponse* response, WFMySQLTask* task) {

		// 任务失败: 及早失败原则
		if (task->get_state() != WFT_STATE_SUCCESS) {
			response->set_statuscode(500);
#ifdef BUG
			std::cerr << "Error: " << WFGlobal::get_error_string(task->get_state(), task->get_error());
#endif
			return;
		}

		MySQLResponse* resp = task->get_resp();
		MySQLResultCursor cursor{ resp };

		if (cursor.get_cursor_status() == MYSQL_STATUS_OK) {
			response->set_statuscode(200);
#ifdef BUG
			std::cout << "signup success! and statuscode  = " << response->statuscode() << "\n";
#endif
		}
		else {
			response->set_statuscode(400);
#ifdef BUG
			std::cout << "signup failed may be name is repetitive" << "\n";
#endif
		}

	}


}//end of anonymous namaspace


class SignUpServiceImpl : public ::l::SignUp::Service
{
public:

	void SignUp(::l::SignUpRequest* request, ::l::SignUpResponse* response, srpc::RPCContext* ctx) override
	{
		//获取username和password
		string username{ request->username() };
		string password{ request->password() };

		//注册
		string hashPassword{};
		string salt{};
		l::CryptoUtil::hashWithSalt(hashPassword, salt, password);

		string url{ MYSQL_URL };
		string sql{ "INSERT INTO users (username, password, salt) VALUES(" };
		sql.append("\"").append(username).append("\",\"").append(hashPassword).append("\",\"").append(salt).append("\")");

#ifdef BUG
		std::cout << "signup sql: " << sql << "\n";
#endif

		WFMySQLTask* task = WFTaskFactory::create_mysql_task(MYSQL_URL, RE_TRY_MAX, std::bind(handleSignUp, response, std::placeholders::_1));

		task->get_req()->set_query(sql);

		SeriesWork* series = ctx->get_series();
		series->push_back(task);

	}
};

int main()
{


	signal(SIGINT, sig_handler);

	SRPCServer server;

	SignUpServiceImpl signup_impl;
	server.add_service(&signup_impl);

	if (server.start(DEFAULT_SIGNUP_PORT) == 0) {
		wait_group.wait();
		server.stop();
	}
	else {
#ifdef BUG
		std::cout << "SignUp server start failed\n";
#endif
	}

	google::protobuf::ShutdownProtobufLibrary();
	return 0;
}
